

export enum JAPIMethod{
    POST = "POST",
    GET = "GET",
}

export interface JAPIConfig{
    baseURL?:string; //baseURL 默认HTTP头
    headers?:{[key:string]:string},
    timeout?:number; //超时时间
    responseType?:XMLHttpRequestResponseType,
    isOnce?:boolean;
}

export interface JAPIData{
    data:any;
}

export interface JAPIGetData{
    responseType?:XMLHttpRequestResponseType,
    params?:any
}

export class JAPI {

    config:JAPIConfig = {
        headers:{
            "Content-Type":"application/json; charset=utf-8"
        }
    };

    requestInterceptors:((config:JAPIConfig) => boolean)[] = [];
    responseInterceptors:((data:JAPIData) => void)[] = [];

    //当前正在请求的URL
    static urls:string[] = [];

    constructor(config:JAPIConfig = {}){

        Object.assign(this.config,config);

        this.config.baseURL = config.baseURL || "";
        this.config.timeout = config.timeout || 5000;
        this.config.headers = config.headers || {
            "Content-Type":"application/json; charset=utf-8"
        };
        this.config.responseType = config.responseType || "json";

    }

    static create(config:JAPIConfig = {}){
        return new JAPI(config);
    }

    post(url:string,data:{} = {},isOnce:boolean = false):Promise<JAPIData>{

        let config:JAPIConfig = Object.assign({},this.config);
        config.isOnce = isOnce;
        if(!(this.onRequestInterceptors(config))) return;
        return new Promise((resolve,reject) => {

            JAPI.request(`${config.baseURL}${url}`,JAPIMethod.POST,data,config,resolve,reject);
            
        })

    }

    static get(url:string,data:JAPIGetData = {},isOnce:boolean = false):Promise<JAPIData>{

        return new Promise((resolve,reject) => {

            JAPI.request(`${url}`,JAPIMethod.GET,data,{isOnce},resolve,reject);

        })

    }
    get(url:string,data:JAPIGetData = {},isOnce:boolean = false):Promise<JAPIData>{

        data.responseType = data.responseType || this.config.responseType;
        data.params = data.params || {};

        let config:JAPIConfig = Object.assign({},this.config);
        config.responseType = data.responseType;
        config.isOnce = isOnce;

        if(!(this.onRequestInterceptors(config))) return;

        return new Promise((resolve,reject) => {

            JAPI.request(`${config.baseURL}${url}`,JAPIMethod.GET,data,config,resolve,reject);

        })

    }

    onRequestInterceptors(config:JAPIConfig){
        //执行拦截器
        for (let index = 0; index < this.requestInterceptors.length; index++) {
            const inter = this.requestInterceptors[index];
            if(!inter(config)) return false;
        }
        return true;
    }

    //请求拦截
    addRequestInterceptors(inter:(config:JAPIConfig) => boolean){
        this.requestInterceptors.push(inter);
    }
    //响应拦截
    addResponseInterceptors(inter:(config:JAPIData) => boolean){
        this.responseInterceptors.push(inter);
    }

    static request(url:string,method:JAPIMethod,data:{} = {},config:JAPIConfig = {},resolve:Function = (data:JAPIData) => {},reject:Function = (data:JAPIData) => {}){

        if(config.isOnce){
            if(this.urls.indexOf(url) >= 0){
                // reject({data:null});
                return;
            }
            this.urls.push(url);
            let resolve1:Function = resolve;
            let reject1 = reject;
            resolve = (data:JAPIData) => {
                this.urls.splice(this.urls.indexOf(url),1)
                resolve1(data);
            }
            reject = (data:JAPIData) => {
                this.urls.splice(this.urls.indexOf(url),1)
                reject1(data);
            }
        }

        config.headers = config.headers || {};
        let result:JAPIData = {
            data:null
        };

        //如果有axios 则使用 axios
        let axios;
        if(axios = window['axios']){

            axios({
                method: method,
                url: url,
                data,
                responseType:config.responseType,
                headers:config.headers
            }).then(response => {
                result.data = response.data
                resolve(result);
            }).catch(() => {
                reject(result);
            });

        }else{

    
            var xhr = new XMLHttpRequest();
            xhr.responseType = config.responseType;
            xhr.open(method,url,true);
    
            //设置请求头
            Object.keys(config.headers).forEach(key => {
                xhr.setRequestHeader(key, config.headers[key]);
            })
    
            //设置超时
            if(config.timeout){
                xhr.timeout = config.timeout;
                xhr.ontimeout = () => {
                    // console.log("JAPI ontimeout");
                    reject(result);
                }
            }
    
            xhr.onloadend = (data) => {
                // console.log("JAPI onloadend");
            };
            xhr.onerror = (data) => {
                // console.log("JAPI onerror");
                reject(result);
            };
    
            xhr.onreadystatechange = () => {
    
                // console.log("JAPI onreadystatechange",xhr.readyState,xhr.status)
    
                if (xhr.readyState != 4) return;
                if (xhr.status == 200) {
    
                    console.log("JAPI",xhr.response);
    
                    if (xhr.responseType == 'arraybuffer') {
                        // 加载非文本格式
                        result.data = xhr.response;
                        resolve(result);
                        return;
                    }else{
    
                        //默认JSON
                        if(config.responseType == "text")
                            result.data = JSON.parse(xhr.response);
                        if(config.responseType == "json")
                            result.data = xhr.response;
                        resolve(result);
                        return;
    
                    }
    
                }
    
            };
    
            if(method == JAPIMethod.GET){
                xhr.send();
            }else{
                xhr.send(JSON.stringify(data));
            }
    
        }

    }

}

